package ua.kratik.seabattle.game;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ua.kratik.seabattle.game.enums.Direction;
import ua.kratik.seabattle.game.enums.CellState;
import ua.kratik.seabattle.game.exceptions.LogicException;

public class Ship implements Comparable<Ship> {
	
	private static Logger logger = LoggerFactory.getLogger(Ship.class);
	
	/**
	 * Represents ship bean from domain layer
	 */
	private ua.kratik.seabattle.domain.Ship shipBean;

	/**
	 * stern means back part of a sheep
	 */
	private Coordinates sternPosition;

	/**
	 * Direction of ship bow against to shipBean stern
	 */
	private Direction direction;

	/**
	 * Contains coordinates of all cells of a ship
	 */
	private Coordinates[] positionMap;

	/**
	 * Indicates if the shipBean was placed on the map (by user or
	 * automatically)
	 */
	private boolean isPlaced = false;

	public Ship(ua.kratik.seabattle.domain.Ship ship) {
		shipBean = ship;
	}

	public Integer getSize() {
		return this.shipBean.getLength();
	}

	/**
	 * 
	 * @param sternPosition
	 * @param direction
	 * @return coordinates of all cells of current ship
	 */
	public Coordinates[] goTo(Coordinates sternPosition,
									Direction direction) {
		positionMap = getPossibleLocation(sternPosition, direction);
		return positionMap;
	}
	
	public void goTo(Coordinates[] positionMap){
		this.positionMap = positionMap;
	}
	
	public Coordinates[] getPossibleLocation(Coordinates sternPosition,
									Direction direction){
		int size = shipBean.getLength();
		Coordinates stern = sternPosition;
		Coordinates[] pos = new Coordinates[size];
		pos[0] = stern;
		for (int i = 1; i < size; i++) {
			switch (direction) {
			case NORTH:
				pos[i] = new Coordinates(stern.getX(), stern.getY() - i);
				break;
			case SOUTH:
				pos[i] = new Coordinates(stern.getX(), stern.getY() + i);
				break;
			case WEST:
				pos[i] = new Coordinates(stern.getX() - i, stern.getY());
				break;
			case EAST:
				pos[i] = new Coordinates(stern.getX() + i, stern.getY());
				break;
			default:
				logger.error("Unimplemmented direction '" + direction.getValue() + "'");
				throw new IllegalArgumentException("Illegal direction: '" + direction.getValue() + "'");
			}
		}
		return pos;
	}

	/**
	 * 
	 * @return coordinates of all cells of current ship
	 */
	public Coordinates[] getPositionMap() {
		return positionMap;
	}

	public ua.kratik.seabattle.domain.Ship getShipBean() {
		return shipBean;
	}

	public Coordinates getSternPosition() {
		return sternPosition;
	}

	public Direction getDirection() {
		return direction;
	}

	public boolean isPlaced() {
		return isPlaced;
	}
	
	//???
//	public CellState getGeneralState(SeaMap seaMap){
//		
//		seaMap.
//		
//		CellState state = CellState.CONTAIN_SHIP;
//		
//		List<CellState> allStates = seaMap.getCellsState(positionMap);
//		boolean containShip = false;
//		boolean containHit = false;
//		boolean containDestroyed = false;
//		//if all are hit then change state to Destroyed
//		for(CellState s: allStates){
//			switch(s){
//			case CONTAIN_SHIP:
//				containShip = true;
//				break;
//			case SHOT_AND_HIT:
//				containHit = true;
//				break;
//			case SHOT_AND_DESTROYED:
//				containDestroyed = true;
//				state = CellState.SHOT_AND_DESTROYED;
//				break;
//			default:
//				logger.error("Square state" + s.name() + " can not be processed");
//				throw new IllegalArgumentException("Square state" + s.name() + " can not be processed");
//			}
//			//validation
//			if(containDestroyed && (containShip || containHit)){
//				throw new LogicException("Parts of ship cannot be DESTROYED and HIT (or CONTAIN_SHIP) at the same time");
//			}
//			
//			if(containHit){
//				if(containShip){
//					state = CellState.SHOT_AND_HIT;
//				} else{
//					//seaMap.fillCells(positionMap, CellState.SHOT_AND_DESTROYED);
//					state = CellState.SHOT_AND_DESTROYED;
//				}
//			}else{
//				state = CellState.CONTAIN_SHIP;
//			}
//		}
//		return state;
//	}
	/**
	 * Sorts the specified list into descending order according to the size
	 */
	public int compareTo(Ship o) {
		return o.getSize().compareTo(this.getSize());
	}

	public int getAlliveCellsCount(SeaMap seaMapToSearch) {
		int count = 0;
		for(Coordinates cell: this.getPositionMap()){
			if(seaMapToSearch.getCellState(cell) == CellState.CONTAIN_SHIP){
				count++;
			}
		}
		return count;
	}

}
